﻿using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Rhino.Mocks;
using StockholmsStad.Web.UI.Class.Controller;
using StockholmsStad.Web.UI.Class.Interfaces;
using StockholmsStad.Web.UI.Class.Model;
using StockholmsStad.Web.UI.Class.Utilities;
using StockholmsStad.Web.UI.UIServiceReference;

namespace StockholmsStad.Web.UI.Test
{
    /// <summary>
    ///This is a test class for OurBookingControllerTest and is intended
    ///to contain all OurBookingControllerTest Unit Tests
    ///</summary>
    [TestClass()]
    public class OurBookingControllerTest
    {
        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext { get; set; }

        #region Additional test attributes

        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //

        #endregion

        /// <summary>
        ///A test for PageLoad
        ///</summary>
        [TestMethod()]
        public void PageLoadTest()
        {
            var mocks = new MockRepository();
            var view = mocks.StrictMock<IVarBokning>();
            var session = new DictionarySessionAdapter(new Dictionary<string, object>());
            var facade = mocks.StrictMock<IServiceFacade>();
            IHttpContextAdapter context = mocks.StrictMock<IHttpContextAdapter>();
            var bookingModel = new BookingModel(session, facade);
            LoginModel loginModel = new LoginModel(session, facade, context);
            var target = new OurBookingController(bookingModel, loginModel, view);
            User user = new User {CoupleId = 2, TicketId = 4, Username = "Svenne@snorslev.ne"};
            loginModel.User = user;
            // Object
            Booking booking = new Booking
                                  {
                                      BookingCode = "code",
                                      CeremonyType = CeremonyType.Individual,
                                      DateTime = new TimeBlock {StartDateTime = new DateTime(2008, 10, 10)}
                                  };
            History[] historyList = new History[]
                                        {
                                            new History()
                                                {
                                                    DateTime = new DateTime(2008, 01, 01, 13, 14, 15),
                                                    Description = "Desc1"
                                                },
                                            new History()
                                                {
                                                    DateTime = new DateTime(2008, 01, 01, 13, 16, 15),
                                                    Description = "Desc2"
                                                },
                                        };
            string[] historyListStrings = new string[] {"hi1", "hi2"};

            //Expect
            Expect.Call(context.IsAuthenticated()).Return(true);
            Expect.Call(facade.GetBooking(user)).Return(booking);
            Expect.Call(() => view.UpdateBooking(booking, "Annan plats"));
            Expect.Call(context.IsAuthenticated()).Return(true);
            Expect.Call(facade.GetHistoryForCurrentUser(user)).Return(historyList);
            Expect.Call(view.FormatLog(historyList[0].DateTime, historyList[0].Description)).Return(
                historyListStrings[0]);
            Expect.Call(view.FormatLog(historyList[1].DateTime, historyList[1].Description)).Return(
                historyListStrings[1]);
            Expect.Call(() => view.SetHistory(historyListStrings));
            // Execute
            mocks.ReplayAll();
            target.PageLoad();
            mocks.VerifyAll();
        }

        /// <summary>
        ///A test for CancelBooking. Individual booking
        ///</summary>
        [TestMethod()]
        public void CancelBookingTest()
        {
            var mocks = new MockRepository();
            var confirmView = mocks.StrictMock<IVarBokning>();
            var session = new DictionarySessionAdapter(new Dictionary<string, object>());
            var facade = mocks.StrictMock<IServiceFacade>();
            IHttpContextAdapter context = mocks.StrictMock<IHttpContextAdapter>();
            var bookingModel = new BookingModel(session, facade);
            LoginModel loginModel = new LoginModel(session, facade, context);
            var target = new OurBookingController(bookingModel, loginModel, confirmView);
            User user = new User {CoupleId = 2, TicketId = 4, Username = "Svenne@snorslev.ne"};
            loginModel.User = user;
            Booking booking = new Booking
                                  {
                                      BookingCode = "code",
                                      CeremonyType = CeremonyType.Individual,
                                      DateTime = new TimeBlock {StartDateTime = new DateTime(2008, 10, 10)}
                                  };
            bookingModel.Booking = booking;
            booking = Booking.createEmptyBooking();
            Expect.Call(context.IsAuthenticated()).Return(true);
            Action<User, Booking> compareArguments = (userTest, bookingTest) =>
                                                         {
                                                             Assert.AreSame(user, userTest);
                                                             AssertAreEqual(booking, bookingTest);
                                                         };
            Expect.Call(() => facade.RegisterBooking(user, booking)).IgnoreArguments().Do(
                compareArguments);
            mocks.ReplayAll();
            target.CancelBooking();
            Assert.IsNull(bookingModel.Booking.DateTime);
            mocks.VerifyAll();
        }

        private static void AssertAreEqual(Booking booking, Booking test)
        {
            Assert.AreEqual(booking.BookingCode, test.BookingCode);
            Assert.AreEqual(booking.BookingMadeBeforeLogin, test.BookingMadeBeforeLogin);
            Assert.AreEqual(booking.CeremonyType, test.CeremonyType);
            Assert.AreEqual(booking.DateTime, test.DateTime);
            Assert.AreEqual(booking.PreferredDate1, test.PreferredDate1);
            Assert.AreEqual(booking.PreferredDate2, test.PreferredDate2);
        }

        /// <summary>
        ///A test for CancelBooking. Ordinary booking
        ///</summary>
        [TestMethod()]
        public void CancelBookingTest2()
        {
            var mocks = new MockRepository();
            var confirmView = mocks.StrictMock<IVarBokning>();
            var session = new DictionarySessionAdapter(new Dictionary<string, object>());
            var facade = mocks.StrictMock<IServiceFacade>();
            IHttpContextAdapter context = mocks.StrictMock<IHttpContextAdapter>();
            var bookingModel = new BookingModel(session, facade);
            LoginModel loginModel = new LoginModel(session, facade, context);
            var target = new OurBookingController(bookingModel, loginModel, confirmView);
            User user = new User {CoupleId = 2, TicketId = 4, Username = "Svenne@snorslev.ne"};
            loginModel.User = user;
            Booking booking = new Booking
                                  {
                                      BookingCode = null,
                                      CeremonyType = CeremonyType.Ordinary,
                                      DateTime = new TimeBlock {StartDateTime = new DateTime(2008, 10, 10)},
                                      PreferredDate1 = new TimeBlock {StartDateTime = new DateTime(2008, 10, 1)},
                                      PreferredDate2 = new TimeBlock {StartDateTime = new DateTime(2008, 10, 2)},
                                  };
            bookingModel.Booking = booking;
            booking = Booking.createEmptyBooking();
            Expect.Call(context.IsAuthenticated()).Return(true);
            Action<User, Booking> compareArguments = (userTest, bookingTest) =>
                                                         {
                                                             Assert.AreSame(user, userTest);
                                                             AssertAreEqual(booking, bookingTest);
                                                         };
            Expect.Call(() => facade.RegisterBooking(user, booking)).IgnoreArguments().Do(
                compareArguments);
            mocks.ReplayAll();
            target.CancelBooking();
            Assert.IsNull(bookingModel.Booking.DateTime);
            Assert.IsNull(bookingModel.Booking.PreferredDate1);
            Assert.IsNull(bookingModel.Booking.PreferredDate2);
            mocks.VerifyAll();
        }

        /// <summary>
        ///A test for OurBookingController Constructor
        ///</summary>
        [TestMethod()]
        public void OurBookingControllerConstructorTest()
        {
            const IBookingModel bookingModel = null;
            const IVarBokning view = null;
            const ILoginModel loginModel = null;
            OurBookingController target = new OurBookingController(bookingModel, loginModel, view);
            Assert.IsNotNull(target);
        }
    }
}